package com.gitee.hermer.boot.jee.commons.bean.utils;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.beanutils.PropertyUtils;

import com.gitee.hermer.boot.jee.commons.collection.CollectionUtils;
import com.gitee.hermer.boot.jee.commons.exception.ErrorCode;
import com.gitee.hermer.boot.jee.commons.exception.PaiUException;
import com.gitee.hermer.boot.jee.commons.reflect.ClassUtils;
import com.gitee.hermer.boot.jee.commons.verify.Assert;

public class BeanCopyUtils {
	
	
	/**
	 * copy属性值
	 * @param source源
	 * @param target目标
	 * @throws InvocationTargetException 
	 * @throws IllegalAccessException 
	 * @throws InstantiationException 
	 * @throws NoSuchMethodException 
	 */
	public static void copyProperties(Object source, Object target) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException, InstantiationException {
		copyProperties(source, target, null, null, true);
	}

	/**
	 * copy属性值，不copy为空的属性值
	 * @param source源
	 * @param target目标
	 * @throws InvocationTargetException 
	 * @throws IllegalAccessException 
	 * @throws InstantiationException 
	 * @throws NoSuchMethodException 
	 */
	public static void copyNotNullProperties(Object source, Object target) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException, InstantiationException {
		copyProperties(source, target, null, null, false);
	}

	/**
	 * copy属性值
	 * @param source 源
	 * @param target 目标
	 * @param includes 复制哪些属性
	 * @param excludes 排除哪些属性
	 * @param copyNotNullProperty 是否copy为空的属性
	 * @throws InvocationTargetException 
	 * @throws IllegalAccessException 
	 * @throws NoSuchMethodException 
	 * @throws InstantiationException 
	 */
	public static void copyProperties(Object source, Object target, String[] includes, String[] excludes, Boolean copyNotNullProperty) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException, InstantiationException {
		if(CollectionUtils.isNotEmpty(includes)){
			for (String string : includes) {
				BeanUtils.copyProperty(target, string, BeanUtils.getProperty(source, string));
			}
		}else if(CollectionUtils.isNotEmpty(excludes)){
			Object temp = BeanUtils.cloneBean(source);
			for (String string : excludes) {
				BeanUtils.setProperty(temp, string, null);
			}
			BeanUtils.copyProperties(temp, target);
		}else{
			BeanUtils.copyProperties(source, target);
		}
	}
	/**
	 * 
	 * @Title: 
	 * @Description: Bean转Map<String,String>
	 * @param: @param bean
	 * @param: @return
	 * @param: @throws IllegalAccessException
	 * @param: @throws InvocationTargetException
	 * @param: @throws NoSuchMethodException       
	 * @date: 2017-9-30 下午3:00:11
	 * @throws
	 */
	public  static Map<String, String> describe(Object bean) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException{
		return BeanUtils.describe(bean);
	}
	/**
	 * 
	 * @Title: 
	 * @Description: Bean转Map<String,String>
	 * @param: @param entity
	 * @param: @return
	 * @param: @throws IllegalAccessException
	 * @param: @throws InvocationTargetException
	 * @param: @throws NoSuchMethodException
	 * @param: @throws PaiUException       
	 * @author:  涂孟超
	 * @date: 2017年10月8日 下午5:17:28
	 * @throws
	 */
	public static Map<String, String> describeMap(Object entity) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException, PaiUException{
		java.lang.reflect.Field[] fields = entity.getClass().getDeclaredFields();
		Map<String, String> params = new HashMap<String, String>();
		
		String prefix = ClassUtils.getClassName(entity.getClass());
		for (Field field : fields) {
			String name = field.getName();
			if(PropertyUtils.isReadable(entity, name)) {
				String key = prefix+'.'+name;
				params.put(key.toLowerCase(), BeanUtils.getProperty(entity, name));
	        }
		}
		Assert.notNullCode(params, ErrorCode.SYSTEM_ERROR,"Map为空.");
		return params;
	}
	

	/**
	 * copy属性值
	 * @param source 源
	 * @param target 目标
	 * @param includes 复制哪些属性
	 * @throws InvocationTargetException 
	 * @throws IllegalAccessException 
	 * @throws InstantiationException 
	 * @throws NoSuchMethodException 
	 */
	public static void copyPropertiesInclude(Object source, Object target, String[] includes) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException, InstantiationException {
		copyProperties(source, target, includes, null, true);
	}

	/**
	 * copy属性值，不copy为空的属性值
	 * @param source 源
	 * @param target 目标
	 * @param includes 复制哪些属性
	 * @throws InvocationTargetException 
	 * @throws IllegalAccessException 
	 * @throws InstantiationException 
	 * @throws NoSuchMethodException 
	 */
	public static void copyNotNullPropertiesInclude(Object source, Object target, String[] includes) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException, InstantiationException {
		copyProperties(source, target, includes, null, false);
	}

	/**
	 * copy属性值
	 * @param source 源
	 * @param target 目标
	 * @param excludes 排除哪些属性
	 * @throws InvocationTargetException 
	 * @throws IllegalAccessException 
	 * @throws InstantiationException 
	 * @throws NoSuchMethodException 
	 */
	public static void copyPropertiesExclude(Object source, Object target, String[] excludes) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException, InstantiationException {
		copyProperties(source, target, null, excludes, true);
	}

	/**
	 * copy属性值，不copy为空的属性值
	 * @param source 源
	 * @param target 目标
	 * @param excludes 排除哪些属性
	 * @throws InvocationTargetException 
	 * @throws IllegalAccessException 
	 * @throws InstantiationException 
	 * @throws NoSuchMethodException 
	 */
	public static void copyNotNullPropertiesExclude(Object source, Object target, String[] excludes) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException, InstantiationException {
		copyProperties(source, target, null, excludes, false);
	}
	
	
	
	
	

}
